#include "stringbuilder.h"

#include "os/os.h"

#include <string.h>
#include <stdarg.h>

namespace l8
{

StringBuilder::StringBuilder(int size)
{
    buffer_ = Vector<char>::New(size);
    position_ = 0;
}


void StringBuilder::AddString(const char* s)
{
    AddSubstring(s, strlen(s));
}


void StringBuilder::AddSubstring(const char* s, int n) {
    ASSERT(!is_finalized() && position_ + n < buffer_.length());
    ASSERT(static_cast<size_t>(n) <= strlen(s));
    memcpy(&buffer_[position_], s, n * kCharSize);
    position_ += n;
}


void StringBuilder::AddFormatted(const char* format, ...) {
    ASSERT(!is_finalized() && position_ < buffer_.length());
    va_list args;
    va_start(args, format);
    int n = OS::VSNPrintF(buffer_ + position_, format, args);
    va_end(args);
    if (n < 0 || n >= (buffer_.length() - position_)) {
        position_ = buffer_.length();
    } else {
        position_ += n;
    }
}


void StringBuilder::AddPadding(char c, int count) {
    for (int i = 0; i < count; i++) {
        AddCharacter(c);
    }
}


char* StringBuilder::Finalize() {
    ASSERT(!is_finalized() && position_ < buffer_.length());
    buffer_[position_] = '\0';
    // Make sure nobody managed to add a 0-character to the
    // buffer while building the string.
    ASSERT(strlen(buffer_.start()) == static_cast<size_t>(position_));
    position_ = -1;
    ASSERT(is_finalized());
    return buffer_.start();
}

} // namespace l8

